package com.fbs.job.core.biz.impl;

import com.fbs.job.core.biz.ExecutorBiz;
import com.fbs.job.core.biz.model.LogParam;
import com.fbs.job.core.biz.model.LogResult;
import com.fbs.job.core.biz.model.TriggerParam;
import com.fbs.job.core.enums.ExecutorBlockStrategyEnum;
import com.fbs.job.core.executor.FbsJobExecutor;
import com.fbs.job.core.glue.GlueTypeEnum;
import com.fbs.job.core.handler.IJobHandler;
import com.fbs.job.core.log.FbsJobFileAppender;
import com.fbs.job.core.model.ResultT;
import com.fbs.job.core.thread.JobThread;

import java.util.Date;

public class ExecutorBizImpl implements ExecutorBiz {
    @Override
    public ResultT<String> beat() {
        return null;
    }

    @Override
    public ResultT<String> run(TriggerParam triggerParam) {
        // load old：jobHandler + jobThread
        JobThread jobThread = FbsJobExecutor.loadJobThread(triggerParam.getJobId());
        IJobHandler jobHandler = jobThread!=null?jobThread.getHandler():null;
        String removeOldReason = null;

        // valid：jobHandler + jobThread
        GlueTypeEnum glueTypeEnum = GlueTypeEnum.match(triggerParam.getGlueType());
        if (GlueTypeEnum.BEAN == glueTypeEnum) {
            // new jobhandler
            IJobHandler newJobHandler = FbsJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());

            // valid old jobThread
            if (jobThread!=null && jobHandler != newJobHandler) {
                // change handler, need kill old thread
                removeOldReason = "change jobhandler or glue type, and terminate the old job thread.";
                jobThread = null;
                jobHandler = null;
            }

            // valid handler
            if (jobHandler == null) {
                jobHandler = newJobHandler;
                if (jobHandler == null) {
                    return new ResultT<String>(ResultT.FAIL_CODE, "job handler [" + triggerParam.getExecutorHandler() + "] not found.");
                }
            }

        }else {
            return new ResultT<String>(ResultT.FAIL_CODE, "glueType[" + triggerParam.getGlueType() + "] is not valid.");
        }

        // executor block strategy
        if (jobThread != null) {
            ExecutorBlockStrategyEnum blockStrategy = ExecutorBlockStrategyEnum.match(triggerParam.getExecutorBlockStrategy(), null);
            if (ExecutorBlockStrategyEnum.DISCARD_LATER == blockStrategy) {
                // discard when running
                if (jobThread.isRunningOrHasQueue()) {
                    return new ResultT<String>(ResultT.FAIL_CODE, "block strategy effect："+ExecutorBlockStrategyEnum.DISCARD_LATER.getTitle());
                }
            } else if (ExecutorBlockStrategyEnum.COVER_EARLY == blockStrategy) {
                // kill running jobThread
                if (jobThread.isRunningOrHasQueue()) {
                    removeOldReason = "block strategy effect：" + ExecutorBlockStrategyEnum.COVER_EARLY.getTitle();

                    jobThread = null;
                }
            } else {
                // just queue trigger
            }
        }


        // replace thread (new or exists invalid)
        if (jobThread == null) {
            jobThread = FbsJobExecutor.registerJobThread(triggerParam.getJobId(), jobHandler, removeOldReason);
        }

        // push data to queue
        ResultT<String> pushResult = jobThread.pushTriggerQueue(triggerParam);
        return pushResult;
    }



    @Override
    public ResultT<LogResult> log(LogParam logParam) {
        // log filename: logPath/yyyy-MM-dd/9999.log
        String logFileName = FbsJobFileAppender.makeLogFileName(new Date(logParam.getLogDateTim()), logParam.getLogId());

        LogResult logResult = FbsJobFileAppender.readLog(logFileName, logParam.getFromLineNum());
        return new ResultT<LogResult>(logResult);
    }
}
